using System;

namespace SharpMud.Net.Telnet.IAC
{
	internal class ControlCodeRegistry
	{
		private System.Collections.ArrayList _ControlCodes;
		
		public ControlCodeRegistry()
		{
			_ControlCodes = new System.Collections.ArrayList();
			this.ReadFromStaticList(typeof(ControlCodes));
		}

		public void Add(ControlCode cc)
		{
			if(_ControlCodes.Contains(cc))
				return;

			if(this.Evaluate(cc.Value)!=null)
			{
				if(this.Evaluate(cc.Value).Name.Trim().ToLower()!=cc.Name.Trim().ToLower())
				{
					throw new InvalidOperationException("The IAC control-code already exists in the control-code registry with the same value but an alternative alias.");
				}
			}
			if(this.Evaluate(cc.Name)!=null)
			{
				if(this.Evaluate(cc.Name).Value!=cc.Value)
				{
					throw new InvalidOperationException("The IAC control-code already exists in the control-code registry under the same alias with an alternative value.");
				}
			}

			this._ControlCodes.Add(cc);
		}
		public void Add(string controlCodeName, byte controlCodeValue)
		{
			this.Add(new ControlCode(controlCodeName,controlCodeValue));
		}

		public ControlCode Evaluate(byte controlCodeValue)
		{
			foreach(ControlCode cc in _ControlCodes)
			{
				if(cc.Value==controlCodeValue)
					return cc;
			}
			return null;
		}

		public ControlCode Evaluate(string controlCodeName)
		{
			foreach(ControlCode cc in _ControlCodes)
			{
				if(cc.Name.Trim().ToLower()==controlCodeName.Trim().ToLower())
					return cc;
			}
			return null;
		}

		private void ReadFromStaticList(System.Type type)
		{
			/*
			System.Reflection.MemberInfo[]  mis = type.GetMembers(System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public);
			foreach(System.Reflection.FieldInfo fi in mis)
			{
				if(fi.FieldType==typeof(ControlCode) || fi.FieldType.IsSubclassOf(typeof(ControlCode)))
				{
					this.Add((ControlCode)fi.GetValue(null));
				}
			}
			*/
		}

		#region Globalization
		private static ControlCodeRegistry _GlobalInstance;
		public static ControlCodeRegistry GlobalInstance
		{
			get
			{
				if(_GlobalInstance==null)
				{
					_GlobalInstance = new ControlCodeRegistry();
				}
				return _GlobalInstance;
			}
		}
		public void GoGlobal()
		{
			if(_GlobalInstance==null)
			{
				_GlobalInstance = this;
			}
			else if(_GlobalInstance==this)
			{
				return;	
			}
			else
			{
				throw new InvalidOperationException("There is already a different globally established ControlCodeRegistry.");
			}
		}
		public void RetractGlobal()
		{
			if(_GlobalInstance==this)
			{
				_GlobalInstance = null;
			}
			else
			{
				throw new InvalidOperationException("The ControlCodeRegistry cannot be retracted from global status because it isn't global.");
			}
		}
		#endregion
	}
}
